<?php
/**
* @author  Oliver Leisalu, Inditel Meedia
* @package DomXml
*/ 
class DomXml extends DomXmlNode {
	
	/**
	 * Node class name that will be used. It must extend to DomXmlNode
	 *
	 * @var String
	 */
	private $nodeClassName = 'DomXmlNode';
	
	/**
	 * Xml parser resource
	 *
	 * @var resource
	 */
	private $parser;
	/**
	 * Nodes that are being currently parsed.
	 *
	 * @var Array
	 */
	private $openNodes = array();
	/**
	 * last open node
	 *
	 * @var unknown_type
	 */
	private $lastOpenNode;

	/**
	 * @param String $data Xml data
	 */
	public function __construct( $data = NULL ) {
		$this->parser = xml_parser_create();
		xml_set_object($this->parser, $this);
		xml_set_element_handler($this->parser, "tag_open", "tag_close");
		xml_set_character_data_handler($this->parser, "cdata");
		xml_parser_set_option( $this->parser, XML_OPTION_CASE_FOLDING, false);
		$this->parse( $data );
	}
	
	
	
	/**
	 * @internal
	 * @param String $data Xml data
	 */
	private function parse( $data ) {
		try {
			$result = xml_parse($this->parser, $data);
			if( $result == 0) {
				throw new RuntimeException( xml_error_string($this->parser).' on '.xml_get_current_line_number($this->parser).':'.xml_get_current_column_number($this->parser), xml_get_error_code($this->parser));
			}
		} catch( Exception $e ) {
			throw $e;
		}
	}
	/**
	 * @internal
	 * @param Resource $parser
	 * @param String $tag
	 * @param String $attributes
	 */
	public function tag_open($parser, $tag, $attributes)  {

		$clName = $this->nodeClassName;
		
		if( ($n = strpos($tag, ':')) > 0 ) {
			$ns = substr($tag,0,$n);
			$tag = substr($tag,$n+1);
		} else {
			$ns = '';
		}
		
		$node = new $clName( $tag );
		$node->setNamespace( $ns );
		$node->setAttributes( $attributes );
		
		if( $this->lastOpenNode == NULL ){
			$this->addChildNode( $node );
		} else {
			$this->lastOpenNode->addChildNode($node);
			$this->openNodes[] = $this->lastOpenNode;
		}
		$this->lastOpenNode = $node;
	}
	/**
	 * @internal
	 * @param Resource $parser
	 * @param String $cdata
	 */
	public  function cdata($parser, $cdata) {
		$this->lastOpenNode->addValue( $cdata );
	}
	/**
	 * @internal
	 * @param Resource $parser
	 * @param String $tag
	 */
	public function tag_close($parser, $tag) {
		$this->lastOpenNode = array_pop( $this->openNodes );
	}
	
	
	
	
	/**
	 * @param String $name
	 */
	public function setNodeClassName( $name ) {
		$this->nodeClassName = $name;
	}

	public function __toString() {
		$xml = '';
		foreach( $this->childNodes as $child )
			$xml .= $child->__toString();
			
		return $xml;
	}

}
?>